﻿#include "MeasureView/UnitConvert.h"
#include <QDebug>
namespace Qly {

UnitConvert::UnitConvert()
{
    m_precision = 4;
}

double UnitConvert::convert(UnitConvert::LENGTH_UNIT inUnit, double value, UnitConvert::LENGTH_UNIT outUnit, QString &valueString, QString &unitString)
{
    double value_m = convertTo_m(inUnit, value);
    double value_out = mToTargetUnit(outUnit, value_m, unitString);

    if(value_out > 100.0) valueString = QString::number(value_out, 'f', 1);
    else if(value_out > 10.0) valueString = QString::number(value_out, 'f', 2);
    else valueString = QString::number(value_out, 'f', 3);
    if(valueString.contains(".")) //有小数点和没有小数点的处理方法不同
    {
        if(valueString.length() < 5)// 有小数点则需要有5个字符
        {
            //在后面补 0，凑足 5 位
            while(valueString.length() < 5)
            {
                valueString.append("0");
            }
        }
    }
    else //没有小数点，说明是整数
    {
        if(valueString.length() < 4)// 整数不够 4 位
        {
            //在后面先补小数点，再补 0，凑足 5 位
            valueString.append(".");
            while(valueString.length() < 4)
            {
                valueString.append("0");
            }

        }
    }

    return value_out;
}

double UnitConvert::convert(UnitConvert::AREA_UNIT inUnit, double value, UnitConvert::AREA_UNIT outUnit, QString &valueString, QString &unitString)
{
    double value_m = convertTo_m2(inUnit, value);
    double value_out = m2ToTargetUnit(outUnit, value_m, unitString);

    if(value_out > 100000.0) valueString = QString::number(value_out, 'f', 0);
    else if(value_out > 10000.0) valueString = QString::number(value_out, 'f', 1);
    else if(value_out > 1000.0) valueString = QString::number(value_out, 'f', 2);
    else if(value_out > 100.0) valueString = QString::number(value_out, 'f', 3);
    else if(value_out > 10.0) valueString = QString::number(value_out, 'f', 4);
    else valueString = QString::number(value_out, 'f', 5);
    if(valueString.contains(".")) //有小数点和没有小数点的处理方法不同
    {
        if(valueString.length() < 7)// 有小数点则需要有7个字符
        {
            //在后面补 0，凑足 7 位
            while(valueString.length() < 7)
            {
                valueString.append("0");
            }
        }
    }
    else //没有小数点，说明是整数
    {
        if(valueString.length() < 6)// 整数不够 6 位
        {
            //在后面先补小数点，再补 0，凑足 7 位
            valueString.append(".");
            while(valueString.length() < 7)
            {
                valueString.append("0");
            }

        }
    }

    return value_out;
}

double UnitConvert::convert2(UnitConvert::LENGTH_UNIT inUnit, double value, UnitConvert::LENGTH_UNIT outUnit, QString &valueString, QString &unitString)
{
    double value_m = convertTo_m(inUnit, value);
    double value_out = mToTargetUnit(outUnit, value_m, unitString);
    valueString = convertToString(value_out, m_precision);
    return value_out;
}

double UnitConvert::convert2(UnitConvert::AREA_UNIT inUnit, double value, UnitConvert::AREA_UNIT outUnit, QString &valueString, QString &unitString)
{
    double value_m = convertTo_m2(inUnit, value);
    double value_out = m2ToTargetUnit(outUnit, value_m, unitString);
    valueString = convertToString(value_out, m_precision);
    return value_out;
}

void UnitConvert::replaceLength(QString &text, double value, QString label, QString unitLabel)
{
    QString valueStr, unitStr;
    if(text.contains(label + "_um"))
    {
        convert2(UnitConvert::um, value, UnitConvert::um, valueStr, unitStr);
        text.replace(label + "_um", valueStr, Qt::CaseSensitive);
        text.replace(unitLabel, unitStr, Qt::CaseSensitive);
    }
    if(text.contains(label + "_mm"))
    {
        convert2(UnitConvert::um, value, UnitConvert::mm, valueStr, unitStr);
        text.replace(label + "_mm", valueStr, Qt::CaseSensitive);
        text.replace(unitLabel, unitStr, Qt::CaseSensitive);
    }
    if(text.contains(label))
    {
        convert2(UnitConvert::um, value, UnitConvert::autoLengthUnit, valueStr, unitStr);
        text.replace(label, valueStr, Qt::CaseSensitive);
        text.replace(unitLabel, unitStr, Qt::CaseSensitive);
    }
}

void UnitConvert::replaceArea(QString &text, double value, QString label, QString unitLabel)
{
    QString area, areaUnit;
    if(text.contains(label + "_um2"))
    {
        convert2(UnitConvert::um2, value, UnitConvert::um2, area, areaUnit);
        text.replace(label + "_um2", area, Qt::CaseSensitive);
        text.replace(unitLabel, areaUnit, Qt::CaseSensitive);
    }
    if(text.contains(label + "_mm2"))
    {
        convert2(UnitConvert::um2, value, UnitConvert::mm2, area, areaUnit);
        text.replace(label + "_mm2", area, Qt::CaseSensitive);
        text.replace(unitLabel, areaUnit, Qt::CaseSensitive);
    }
    if(text.contains(label))
    {
        convert2(UnitConvert::um2, value, UnitConvert::autoAreaUnit, area, areaUnit);
        text.replace(unitLabel, areaUnit, Qt::CaseSensitive);
        text.replace(label, area, Qt::CaseSensitive);
    }
}

double UnitConvert::convertTo_m(UnitConvert::LENGTH_UNIT inUnit, double value)
{
    double value_m = 0.0; // 换算成国际单位制标准单位 m
    switch (inUnit) {
    case km:
        value_m = value * 1e3;
        break;
    case m:
        value_m = value;
        break;
    case cm:
        value_m = value * 1e-2;
        break;
    case mm:
        value_m = value * 1e-3;
        break;
    case um:
        value_m = value * 1e-6;
        break;
    case nm:
        value_m = value * 1e-9;
        break;
    default:
        break;
    }

    return value_m;
}

double UnitConvert::convertTo_m2(UnitConvert::AREA_UNIT inUnit, double value)
{
    double value_m = 0.0; // 换算成国际单位制标准单位 m
    switch (inUnit) {
    case km2:
        value_m = value * 1e6;
        break;
    case m2:
        value_m = value;
        break;
    case cm2:
        value_m = value * 1e-4;
        break;
    case mm2:
        value_m = value * 1e-6;
        break;
    case um2:
        value_m = value * 1e-12;
        break;
    case nm2:
        value_m = value * 1e-18;
        break;
    default:
        break;
    }
    return value_m;
}

double UnitConvert::mToTargetUnit(UnitConvert::LENGTH_UNIT outUnit, double value_m, QString &unitString)
{
    double value_out = 0.0;
    switch (outUnit) {
    case UnitConvert::nm:
        value_out = value_m * 1e9;
        unitString = u8"nm";
        break;
    case UnitConvert::um:
        value_out = value_m * 1e6;
        unitString = u8"μm";
        break;
    case UnitConvert::mm:
        value_out = value_m * 1e3;
        unitString = u8"mm";
        break;
    case UnitConvert::cm:
        value_out = value_m * 1e2;
        unitString = u8"cm";
        break;
    case UnitConvert::m:
        value_out = value_m;
        unitString = u8"m";
        break;
    case UnitConvert::km:
        value_out = value_m * 1e-3;
        unitString = u8"km";
        break;
     case UnitConvert::autoLengthUnit:
        if(fabs(value_m) >= 1e3)
        {
            value_out = value_m * 1e-3;
            unitString = u8"km";
            break;
        }
        if(fabs(value_m) >= 1)
        {
            value_out = value_m;
            unitString = u8"m";
            break;
        }
        if(fabs(value_m) >= 1e-2)
        {
            value_out = value_m * 1e2;
            unitString = u8"cm";
            break;
        }
        if(fabs(value_m) >= 1e-3)
        {
            value_out = value_m * 1e3;
            unitString = u8"mm";
            break;
        }
        if(fabs(value_m) >= 1e-6)
        {
            value_out = value_m * 1e6;
            unitString = u8"μm";
            break;
        }
        value_out = value_m * 1e9;
        unitString = u8"nm";
        break;
    }
    return value_out;
}

double UnitConvert::m2ToTargetUnit(UnitConvert::AREA_UNIT outUnit, double value_m, QString &unitString)
{
    double value_out = 0.0;
    switch (outUnit) {
    case UnitConvert::nm2:
        value_out = value_m * 1e18;
        unitString = u8"nm²";
        break;
    case UnitConvert::um2:
        value_out = value_m * 1e12;
        unitString = u8"μm²";
        break;
    case UnitConvert::mm2:
        value_out = value_m * 1e6;
        unitString = u8"mm²";
        break;
    case UnitConvert::cm2:
        value_out = value_m * 1e4;
        unitString = u8"cm²";
        break;
    case UnitConvert::m2:
        value_out = value_m;
        unitString = u8"m²";
        break;
    case UnitConvert::km2:
        value_out = value_m * 1e-6;
        unitString = u8"km²";
        break;
     case UnitConvert::autoAreaUnit:
        if(fabs(value_m) >= 1e6)
        {
            value_out = value_m * 1e-6;
            unitString = u8"km²";
            break;
        }
        if(fabs(value_m) >= 1)
        {
            value_out = value_m;
            unitString = u8"m²";
            break;
        }
        if(fabs(value_m) >= 1e-4)
        {
            value_out = value_m * 1e4;
            unitString = u8"cm²";
            break;
        }
        if(fabs(value_m) >= 1e-6)
        {
            value_out = value_m * 1e6;
            unitString = u8"mm²";
            break;
        }
        if(fabs(value_m) >= 1e-12)
        {
            value_out = value_m * 1e12;
            unitString = u8"μm²";
            break;
        }
        value_out = value_m * 1e18;
        unitString = u8"nm²";
        break;
    }
    return value_out;

}

QString UnitConvert::convertToString(double value, uint8_t precision)
{
//    QString zero("0");
    QString str = QString::number(value, 'f', precision);
//    int N = str.lastIndexOf('.');
//    if(N < 0)
//    {
//        str.append("." + zero.repeated(precision));
//        return str;
//    }
//    N = str.length() - N;
//    if(N < precision)
//    {
//        qDebug() << "N = " << N << ", precision = " << precision;
//        str.append(zero.repeated(precision - N));
//    }

    return str;
}


void UnitConvert::setPrecision(uint8_t precision)
{
    m_precision = precision;
}

}
